package model;

import java.util.Observable;
import model.info.Constants;
import model.mapping.MapCheckouts;
import model.mapping.MapImageBuilder;
import model.mapping.ModelMapBuilder;
import model.simulation.IndividualsBuilder;
import view.panels.MapPanel;
import agents.SimulationAgent;
import agents.TrafficAgent;
import agents.relations.Environment;
import aglobe.container.agent.Agent;
import aglobe.ontology.AgentInfo;
import aglobe.ontology.Libraries;

public class Model extends Observable {

	public static enum Directions{UP,DOWN,RIGHT,LEFT,RIGHTUP,LEFTUP,RIGHTDOWN,LEFTDOWN};
	public static enum Individuals {NONE,FREE,VEHICLE,PEDESTRIAN};
	public static enum Crossings {TRAFFICLIGHT,ZEBRA,TRAFFICLIGHTANDZEBRA,ISLAND,UNMARKED};
	public static enum LightStates {RED,YELLOW,GREEN};
	public static enum Cardinals {NORTH,SOUTH,EAST,WEST};
	public static enum Vehicles {CAR,TRUCK,VAN}
	//public static enum Positions {Frontal,Atras,Derecha,Izquierda,FrontDer,FrontIzq,AtDer,AtIzq};
	//public static enum RoadStatus {NameAndLane,Name,Forbidden,Opposite}; 
	/*public static enum Instructions {HeadNorth,HeadSouth,HeadEast,HeadWest,TurnRight,TurnLeft,
	SlightRight,SlightLeft,Continue};*/
	//private MapPoint[][] pedestrianMap;
	//private MapPoint[][] generalInfoMap;

	private MapPanel mapPanel;
	private SimulationAgent simulation;
	private MapImageBuilder mapImageBuilder;
	private ModelMapBuilder modelMapBuilder;
	private IndividualsBuilder individualsBuilder;
	private MapCheckouts mapCheckouts;
	private TrafficAgent trafficAgent;
	private Environment environment;
	private Integer simulationSpeed;
	private Boolean stopSimulation;
	

	public Model(SimulationAgent simulation) {
		
		this.simulation = simulation;
		mapImageBuilder = new MapImageBuilder(this);
		modelMapBuilder = new ModelMapBuilder(this);
		individualsBuilder = new IndividualsBuilder(this);
		mapCheckouts = new MapCheckouts(this);
		environment = new Environment();
		individualsBuilder.cleanTypeList();
	}
	
	public SimulationAgent getSimulation() {
		return simulation;
	}

	public void setSimulation(SimulationAgent simulation) {
		this.simulation = simulation;
	}

	public MapImageBuilder getMapImageBuilder() {
		return mapImageBuilder;
	}

	public void setMapImageBuilder(MapImageBuilder imageBuilder) {
		this.mapImageBuilder = imageBuilder;
	}
	
	public ModelMapBuilder getModelMapBuilder() {
		return modelMapBuilder;
	}

	public void setModelMapBuilder(ModelMapBuilder modelBuilder) {
		this.modelMapBuilder = modelBuilder;
	}

	public MapCheckouts getMapCheckouts() {
		return mapCheckouts;
	}

	public void setMapCheckouts(MapCheckouts mapCheckouts) {
		this.mapCheckouts = mapCheckouts;
	}

	public IndividualsBuilder getIndividualsBuilder() {
		return individualsBuilder;
	}

	public void setIndividualsBuilder(IndividualsBuilder agentBuilder) {
		this.individualsBuilder = agentBuilder;
	}
	
	public Boolean getStopSimulation() {
		return stopSimulation;
	}

	public void setStopSimulation(Boolean stop) {
		stopSimulation = stop;
	}

	public Environment getEnvironment() {
		return environment;
	}

	public void setEnvironment(Environment environment) {
		this.environment = environment;
	}

	public TrafficAgent getTrafficAgent() {
		return trafficAgent;
	}

	public void setTrafficAgent(TrafficAgent trafficAgent) {
		this.trafficAgent = trafficAgent;
	}

	public MapPanel getMapPanel() {
		return mapPanel;
	}

	public void setMapPanel(MapPanel mapPanel) {
		this.mapPanel = mapPanel;
	}
	
	public Integer getSimulationSpeed() {
		return simulationSpeed;
	}

	public void setSimulationSpeed(Integer simulationSpeed) {
		this.simulationSpeed = simulationSpeed;
	}
	
	public void resetSpeedSimulation() {
		
		simulationSpeed = 250;
		updateContent(4,simulationSpeed);
	}
	
	public void stopAll() {
		
		if (stopSimulation) {
			if (searchAgent(Constants.TRAFFIC_AGENT) != null)
				trafficAgent.finishExecution();
			for (int i=0;i<mapPanel.getWidth();i++)
				for (int j=0;j<mapPanel.getHeight();j++) {
					if (!modelMapBuilder.getDriverMap()[i][j].getOccupant().equals(Individuals.FREE.ordinal()))
						modelMapBuilder.getDriverMap()[i][j].setOccupant(Individuals.FREE.ordinal());
					//if (!pedestrianMap[i][j].getOcupante().equals(Individuals.Libre.ordinal()))
						//pedestrianMap[i][j].setOcupante(Individuals.Libre.ordinal());
				}
			updateWithoutContent(2);
		}
	}

	public void buildRoadsDrivers() {
		
		modelMapBuilder.generateMap();
		//modelMapBuilder.updateFreePoints();
		modelMapBuilder.putCoordinates();
		modelMapBuilder.generateCrossings();
	}
	
	public void configureEnvironment(Integer typeEnvironment, Integer conditions) {
		
		environment.setTipo(typeEnvironment);
		environment.setCondiciones(conditions);
		updateWithoutContent(3);
	}
	
	public void updateContent(Integer value,Object object) {
		
		LocalMessage message = new LocalMessage(value,object);
		setChanged();
		notifyObservers(message);
	}
	
	public void updateWithoutContent(Integer value) {
		
		LocalMessage message = new LocalMessage(value,null);
		setChanged();
		notifyObservers(message);
	}
	
	public void startSimulation() {
	
		if (!individualsBuilder.getList().isEmpty()) 
			trafficAgent.startSimulation();
	}
	
	public void generateTraffic() {
		
		if (!individualsBuilder.getList().isEmpty()) {
			AgentInfo infoTraffic = new AgentInfo();
			infoTraffic.setReadableName(Constants.TRAFFIC_AGENT);
			infoTraffic.setMainClass(Constants.TRAFFIC_AGENT_ROUTE);
			infoTraffic.setType(Constants.TRAFFIC_AGENT);
			infoTraffic.setLibraries(new Libraries());
			try {
				simulation.getContainer().getAgentManager().createAgent(infoTraffic);
			} catch (Exception e) {
				e.printStackTrace();
			}
			trafficAgent = (TrafficAgent) searchAgent(Constants.TRAFFIC_AGENT);
			if (trafficAgent != null)
				trafficAgent.execTrafficGenerator(this);
			else
				System.err.println("No furula");
		}
	}
	
	public Agent searchAgent(String name) {
		
		Agent agent = null;
		if (simulation.getContainer().getAgentManager().existsAgent(name))
				agent = simulation.getContainer().getAgentManager().getAgentInstance(name);
		return agent;
	}
	
	public Agent searchRunningAgent(String readableName) {
		
		Agent agent = null;
		Boolean found = false;
		for (int i=0;i<simulation.getContainer().getAgentManager().getRunningAgents().size()&&!found;i++) {
			String name = simulation.getContainer().getAgentManager().getRunningAgents().get(i).getReadableName();
			if (name.equals(readableName)) {
				found = true;
				agent = simulation.getContainer().getAgentManager().getAgentInstance(readableName);
			}
		}
		return agent;
	}
	
	public void getEstadistics() {
		
		
	}
}
